#pragma once
#include "BaseEntity.h"
#include "GameState.h"
#include "PlayerModel.h"
#include "Region.h"
#include "SteeringBehaviors.h"

#include <sfml/Graphics.hpp>

class Team;
/*
	BaseClass for our soccer players, with steeringBehaviors.
	AI delegated to specific player definition (goalKeeper ai is different than a fieldplayer's one)
*/

class BasePlayer : public BaseEntity
{
public:
	
	sf::Text pVal; //FIXME!! JUST FOR DEBUG
	float pValNum; //FIXME!! JUST FOR DEBUG

	BasePlayer(GameState* game, Team* team, int homeRegionId, sf::Color drawColor, float maxSpeed);
	virtual ~BasePlayer();

	virtual void				Update(const sf::Input& input);
	virtual void				OnDraw(sf::RenderWindow&);
	virtual void				DrawOnRadar(sf::RenderWindow& window,const sf::Vector2f& offset);
	virtual bool				HandleMessage(const Telegram& msg) = 0;

	SteeringBehaviors* const	Steering()const{ return m_steer; }
	
	inline void					SetTarget(Vector2 pos) { m_steer->SetTarget(pos); }
	inline bool					AtTarget(){ return m_pos == m_steer->GetTarget(); } 

	inline void					SetHomeRegion(int newRegion){ m_home = m_game->GetRegion(newRegion);}
	inline Region* const		GetHomeRegion()const{ return  m_home;}
	Team* const					GetTeam()const{ return  m_team;}

	virtual void				ToHome() = 0;
	virtual bool				AtHome() const { return m_home->Inside(m_pos);}
	virtual Vector2				FindShot() = 0;
	virtual BasePlayer* const	FindPass() = 0;

	GameState* const			Pitch()const{ return m_game; }
	sf::Color					PlayerColor()const{ return m_playerColor; }
	sf::Color					AuraColor()const{ return m_auraColor; }
	inline void					SetAuraColor(sf::Color color){ if (color.a!=0) color.a=180; m_auraColor = color; }
	
	void						Wait(int tick){ m_waitTime = m_clock.GetElapsedTime() + (tick*Params::GameUpdateTime) ;}
	bool						IsWaiting(){ return m_clock.GetElapsedTime() < m_waitTime; }
	
	void						InputWait(int tick){ m_inputWaitTime = m_clock.GetElapsedTime() + (tick*Params::GameUpdateTime) ;}
	bool						IsInputWaiting(){ return m_clock.GetElapsedTime() < m_inputWaitTime; }

	bool						IsControllingPlayer();
	bool						IsClosestTeamPlayerToBall();
	bool						IsSecondClosestTeamPlayerToBall();

	float						DistToBall()const{ return m_distToBall; }
	float						DistToHomeGoal()const{ return m_distToHomeGoal; }
	float						DistToOppGoal()const{ return m_distToOppGoal; }

	float						DistToNearestOpponent()const;
	BasePlayer* const			NearestOpponent()const;

	virtual void				CalculateInterposeWeight() = 0;
	void						Pass(BasePlayer* passTo, const Vector2& passToward = Vector2::ZERO);
	void						Shoot(Vector2 shotDirection);
	bool						IsInHotRegion();

	virtual void				SetUserControl(bool controlled) = 0;
	bool						IsUserControlled();

protected:

	float	CanPass(BasePlayer* passTo);

	Team*				m_team;
	Region*				m_home;
	
	//we use these a lot, so we do math just once every update.
	float				m_distToBall;
	float				m_distToHomeGoal;
	float				m_distToOppGoal;
	
	sf::Color			m_playerColor;
	sf::Color			m_auraColor;

	PlayerModel*		m_model;

private:

	virtual void		UserMove(const sf::Input& input);
	
	void				UserPass(const sf::Input& input);

	void				UserShoot(const sf::Input& input);

	virtual void		UserTackle(const sf::Input& input);

	void				UserChangePlayer(const sf::Input& input);

	GameState*			m_game;
	SteeringBehaviors*	m_steer;

	sf::Clock			m_clock;
	float				m_waitTime;
	float				m_inputWaitTime;

};
